---
title: Executors | Dagster
description: Executors are responsible for executing steps within a pipeline run.
---

# Executors

## Relevant APIs

| Name                                     | Description                             |
| ---------------------------------------- | --------------------------------------- |
| <PyObject object="executor" decorator /> | The decorator used to define executors. |

## Overview

Executors are responsible for executing steps within a pipeline run. Once a run has launched
and the the process for the run, or run worker, has been allocated and started, the executor assumes responsibility
for execution. Executors can range from single-process serial executors all the way to managing
per-step computational resources with a sophisticated control plane.

What executor is used is determined by two things. First, modes provide the _possible_ set of executors one can use. In order to set this use the `executor_defs` property on <PyObject module="dagster" object="ModeDefinition" />. Second, the `execution` config section of the run config determines the actual executor.

Example executors include:

- <PyObject module="dagster" object="in_process_executor" />: Execution plan
  executes serially within the run worker itself.
- <PyObject module="dagster" object="multiprocess_executor" />: Each step
  executes within its own spawned process. Has configurable level of
  parallelism.
- <PyObject module="dagster_dask" object="dask_executor" />: Executes each step
  within a dask task.
- <PyObject module="dagster_celery" object="celery_executor" />: Executes each
  step within a celery task.
- <PyObject module="dagster_celery_docker" object="celery_docker_executor" />:
  Executes each step within a Docker container.
- <PyObject module="dagster_celery_k8s" object="celery_k8s_job_executor" />:
  Executes each step within a ephemeral kubernetes pod, using celery as a
  control plane for prioritization, queuing, and so forth.

## Custom Executors

The executor system is pluggable, and it is possible to write your own executor to target a different execution substrate. This is not well-documented, and the internal APIs continue to be in flux.
